package com.study.jvm.demo.stringtable;

import org.junit.Test;

public class StringTableTest {

    @Test
    public void test() {
        String a = new String("abc");
        String b = new String("def");
    }

    @Test
    public void test0() {
        //String 在使用的时候初始化进StringTable中
        //查看memory 第一次读取会在StringTable中分配 第二次直接使用StringTable
        System.out.println("1");
        System.out.println("2");
        System.out.println("3");
        System.out.println("4");
        System.out.println("5");

        System.out.println("1");
        System.out.println("2");
        System.out.println("3");
        System.out.println("4");
        System.out.println("5");
    }

    @Test
    public void test1() {
        String s1 = "a" + "b" + "c";  // 得到 abc的常量池
        String s2 = "abc"; // abc存放在常量池，直接将常量池的地址返回
        /**
         * 最终java编译成.class，再执行.class
         */
        System.out.println(s1 == s2); // true，因为存放在字符串常量池
        System.out.println(s1.equals(s2)); // true
    }

    @Test
    public void test2() {
        String s1 = "javaEE";
        String s2 = "hadoop";
        String s3 = "javaEEhadoop";
        String s4 = "javaEE" + "hadoop";//编译期优化
        //如果拼接符号的前后出现了变量，则相当于在堆空间中的new String(),具体内容为拼接的结果，javaEEhadoop
        String s5 = s1 + "hadoop";
        String s6 = "javaEE" + s2;
        String s7 = s1 + s2;

        System.out.println(s3 == s4); // true
        System.out.println(s3 == s5); // false
        System.out.println(s3 == s6); // false
        System.out.println(s3 == s7); // false
        System.out.println(s5 == s6); // false
        System.out.println(s5 == s7); // false
        System.out.println(s6 == s7); // false
        //intern(); 判断字符串常量池中是否存在javaEEhadoop值，如果存在则返回常量池中javaEEhadoop的地址；
        //如果自负床常量池中不存在javaEEhadoop，则在常量池中加载一份javaEEhadoop，并且返回对象的地址
        String s8 = s6.intern();
        System.out.println(s3 == s8); // true
    }

    @Test
    public void test3() {
        String a = "a";
        String b = "b";
        String c = "ab";
        /*
        如下的a+b的执行季节：
        1 StringBuilder s = new StringBuilder();
        2 s.append("a")
        3 s.append("b")
        4 s.toString(); --> 约等于 new String("ab");

        补充： 在jdk5之后使用的是StringBuilder,在jdk5之前使用的是StringBuffer
         */
        String d = a + b;
        System.out.println(c == d);//false
    }

    @Test
    public void test4() {
        //字符串拼接不一定使用StringBuilder
        //如果连接符号左右两边都是字符串常量或者常量引用，则任然使用编译期优化，既非StringBuilder的方式

        //针对final的修饰类、方法、基本数据类型、引用数据类型，建议使用final修饰
        final String a = "a";
        final String b = "b";
        String c = "ab";
        String d = a + b;
        System.out.println(c == d);//true
    }

    @Test
    public void test5() {
        String s1 = "javaEEhadoop";
        String s2 = "javaEE";
        String s3 = s2 + "hadoop";
        System.out.println(s1 == s3);

        final String s4 = "javaEE";//s4 常量
        String s5 = s4 + "hadoop";
        System.out.println(s1 == s5);
    }
}